using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Text;
using System.Web.Services;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace MicrosoftFrance.MCS.EPM2007
{
    class PSIResource
    {

        public static DataTable GetResourceDataTable()
        {
            ResourceWS.ResourceDataSet resDataSet = new ResourceWS.ResourceDataSet();
            resDataSet = Program.resource.ReadResources("", false);
            return resDataSet.Resources;
        }

        public static ResourceWS.ResourceDataSet GetResourceDataSet(bool autoCheckOut)
        {
            return Program.resource.ReadResources(string.Empty, autoCheckOut);
        }

        public static ResourceWS.ResourceDataSet GetResourceDataSet(Guid resUID)
        {
            return Program.resource.ReadResource(resUID);
        }

        public static void ForceCheckInOfAllResources()
        {
            ResourceWS.ResourceDataSet resDS = GetResourceDataSet(false);

            List<Guid> resList = new List<Guid>();

            for(int r = 0; r < resDS.Resources.Count; r++)
            {
                if(!resDS.Resources[r].IsRES_CHECKOUTBYNull())
                    resList.Add(resDS.Resources[r].RES_UID);
            }

            if(resList.Count > 0)
                Program.resource.CheckInResources(resList.ToArray(), true);
        }


        //public static ResourceWS.ResourceDataSet GetResourceDataSetForASpecificCF(Guid cfUID)
        //{
        //    ResourceWS.ResourceDataSet resourceDs = new ResourceWS.ResourceDataSet();

        //    PSLibrary.Filter resourceFilter = new PSLibrary.Filter();
        //    resourceFilter.FilterTableName = resourceDs.ResourceCustomFields.TableName;
        //    resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.ResourceCustomFields.TableName, resourceDs.ResourceCustomFields.MD_PROP_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
        //    resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.ResourceCustomFields.TableName, resourceDs.ResourceCustomFields.MD_PROP_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.Asc));
        //    PSLibrary.Filter.FieldOperator fo = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, resourceDs.ResourceCustomFields.MD_PROP_UIDColumn.ColumnName, cfUID);
        //    resourceFilter.Criteria = fo;

        //    return Program.resource.ReadResources(resourceFilter.GetXml(), false);
        //}

        public static void UpdateAllResourcesCustomField(Guid mdPropUID, bool flagValue, AppLog appLog)
        {
            ForceCheckInOfAllResources();

            ResourceWS.ResourceDataSet resDS = GetResourceDataSet(true, false);
            ResourceWS.ResourceDataSet resDS2;

            for (int r = 0; r < resDS.Resources.Count; r++)
            {
                resDS2 = GetResourceDataSet(resDS.Resources[r].RES_UID);

                bool ok = UpdateResourceCustomField(resDS2, mdPropUID, flagValue);

                /*
                Guid cfUID = GetCUSTOM_FIELD_UID(resDS, mdPropUID, resDS.Resources[r].RES_UID);
                ResourceWS.ResourceDataSet.ResourceCustomFieldsRow resCFRow;
                // Remove existing CF row
                if (cfUID != Guid.Empty)
                {
                    resCFRow = resDS.ResourceCustomFields.FindByCUSTOM_FIELD_UID(cfUID);
                    resDS.ResourceCustomFields.RemoveResourceCustomFieldsRow(resCFRow);
                }
                // Add CF row
                resCFRow = AddResourceCustomField(resDS.Resources[r].RES_UID, mdPropUID, false, resDS);
                resDS.ResourceCustomFields.AddResourceCustomFieldsRow(resCFRow);                

                resDS.AcceptChanges();
                Program.resource.UpdateResources(resDS, false, true);
                */
                //appLog.WriteLine(string.Format("Update CF for Resource: {0}", resDS.Resources[r].RES_NAME), false);
            }

           //appLog.WriteLine(string.Format("Updated {0} Resources for Custom Field: {1}", resDS.Resources.Count, mdPropUID), false);
        }

        public static bool UpdateResourceCustomField(ResourceWS.ResourceDataSet resDS, Guid cfUID, bool flagValue)
        {
            Guid cfExists = GetCUSTOM_FIELD_UID(resDS, cfUID);
            if (cfExists != Guid.Empty)
            {
                for (int cf = 0; cf < resDS.ResourceCustomFields.Count; cf++)
                {
                    if (resDS.ResourceCustomFields[cf].MD_PROP_UID == cfUID)
                    {
                        resDS.ResourceCustomFields[cf].FLAG_VALUE = flagValue;
                        return UpdateOneResource(resDS);
                    }
                }
            }
            else
            {
                resDS.ResourceCustomFields.AddResourceCustomFieldsRow(AddResourceCustomField(resDS.Resources[0].RES_UID, cfUID, flagValue, resDS));
                return UpdateOneResource(resDS);
            }   

            return false;
        }

        public static Guid GetCUSTOM_FIELD_UID(ResourceWS.ResourceDataSet resDS, Guid mdPropUid)
        {
            resDS.ResourceCustomFields.DefaultView.RowFilter = "MD_PROP_UID = " + "'" + mdPropUid + "'";
            if (resDS.ResourceCustomFields.DefaultView.Count > 0)
            {
                return new Guid(resDS.ResourceCustomFields.DefaultView[0]["CUSTOM_FIELD_UID"].ToString());
            }
            return Guid.Empty;
        }

        public static Guid GetCUSTOM_FIELD_UID(ResourceWS.ResourceDataSet resDS, Guid mdPropUid, Guid resUid)
        {
            resDS.ResourceCustomFields.DefaultView.RowFilter = "RES_UID = " + "'" + resUid + "' AND MD_PROP_UID = " + "'" + mdPropUid + "'";
            if (resDS.ResourceCustomFields.DefaultView.Count > 0)
            {
                return new Guid(resDS.ResourceCustomFields.DefaultView[0]["CUSTOM_FIELD_UID"].ToString());
            }

            return Guid.Empty;
        }

        public static bool GetCFFlagValue(ResourceWS.ResourceDataSet resDS, Guid mdPropUid, Guid resUid)
        {
            resDS.ResourceCustomFields.DefaultView.RowFilter = "RES_UID = " + "'" + resUid + "' AND MD_PROP_UID = " + "'" + mdPropUid + "'";
            if (resDS.ResourceCustomFields.DefaultView.Count > 0)
            {
                return bool.Parse(resDS.ResourceCustomFields.DefaultView[0]["FLAG_VALUE"].ToString());
            }

            return false;
        }

        public static bool UpdateOneResource(ResourceWS.ResourceDataSet resDS)
        {
            List<Guid> resUIDs = new List<Guid>();
            resUIDs.Add(resDS.Resources[0].RES_UID);
            try
            {
                // Checkout resources first
                if (resDS.Resources[0].IsRES_CHECKOUTBYNull())
                    Program.resource.CheckOutResources(resUIDs.ToArray());
                // Update and checkin resources
                Program.resource.UpdateResources(resDS, false, true);
            }
            catch
            { // do nothing
            }

            return true;
        }

        public static ResourceWS.ResourceDataSet GetResourceDataSet(bool filterWorkResource, bool autoCheckOut)
        {
            if (filterWorkResource)
            {
                ResourceWS.ResourceDataSet resourceDs = new ResourceWS.ResourceDataSet();

                PSLibrary.Filter resourceFilter = new PSLibrary.Filter();
                resourceFilter.FilterTableName = resourceDs.Resources.TableName;
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.Asc));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_IS_WINDOWS_USERColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.WRES_ACCOUNTColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_TYPEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                //resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_TIMESHEET_MGR_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_CHECKOUTBYColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_CHECKOUTDATEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));

                PSLibrary.Filter.FieldOperator existingResource = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, resourceDs.Resources.RES_TYPEColumn.ColumnName, PSLibrary.Resource.Type.WorkResource);
                resourceFilter.Criteria = existingResource;

                return Program.resource.ReadResources(resourceFilter.GetXml(), autoCheckOut);
            }
            else
                return GetResourceDataSet(autoCheckOut);
        }

        public static ResourceWS.ResourceDataSet GetResourceDataSetMGR(bool filterWorkResource, bool autoCheckOut)
        {
            if (filterWorkResource)
            {
                ResourceWS.ResourceDataSet resourceDs = new ResourceWS.ResourceDataSet();

                PSLibrary.Filter resourceFilter = new PSLibrary.Filter();
                resourceFilter.FilterTableName = resourceDs.Resources.TableName;
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.Asc));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_IS_WINDOWS_USERColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.WRES_ACCOUNTColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_TYPEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                //resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_TIMESHEET_MGR_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_CHECKOUTBYColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
                resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_CHECKOUTDATEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));

                PSLibrary.Filter.FieldOperator existingResource = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Like, resourceDs.Resources.RES_NAMEColumn.ColumnName, "Mgr%");
                resourceFilter.Criteria = existingResource;

                return Program.resource.ReadResources(resourceFilter.GetXml(), autoCheckOut);
            }
            else
                return GetResourceDataSet(autoCheckOut);
        }
        
        public static Guid CreateResource(string resname, int type, ResourceWS.ResourceDataSet resDS)
        {
            ResourceWS.ResourceDataSet.ResourcesRow resrow = resDS.Resources.NewResourcesRow();
            resrow.RES_UID = Guid.NewGuid();
            resrow.RES_NAME = resname;
            resrow.RES_TYPE = type;
            resrow.BaseCalendarUniqueId = PSIMethods.GetCalendar("24heures");
            resDS.Resources.AddResourcesRow(resrow);
            return resrow.RES_UID;
        }

        public static ResourceWS.ResourceDataSet.ResourceCustomFieldsRow AddResourceCustomField(Guid resID, Guid mdPropUID, bool flagValue, ResourceWS.ResourceDataSet resDS)
        {
            ResourceWS.ResourceDataSet.ResourceCustomFieldsRow cfrow = resDS.ResourceCustomFields.NewResourceCustomFieldsRow();
            cfrow.RES_UID = resID;
            cfrow.MD_PROP_UID = mdPropUID;
            cfrow.FLAG_VALUE = flagValue;
            cfrow.CUSTOM_FIELD_UID = Guid.NewGuid();

            return cfrow;
        }

        public static void AddResourceCustomField(Guid resID, string name, string value, ResourceWS.ResourceDataSet resDS)
        {
            ResourceWS.ResourceDataSet.ResourceCustomFieldsRow cfrow = resDS.ResourceCustomFields.NewResourceCustomFieldsRow();
            cfrow.RES_UID = resID;
            cfrow.MD_PROP_UID = new Guid(PSICustomFields.GetMD_PROP_UID(name));
            cfrow.TEXT_VALUE = value;
            cfrow.CUSTOM_FIELD_UID = Guid.NewGuid();
            resDS.ResourceCustomFields.AddResourceCustomFieldsRow(cfrow);
        }

        public static void AddResourceCustomField(Guid resID, string name, Guid ltcode, ResourceWS.ResourceDataSet resDS)
        {
            ResourceWS.ResourceDataSet.ResourceCustomFieldsRow cfrow = resDS.ResourceCustomFields.NewResourceCustomFieldsRow();
            cfrow.RES_UID = resID;
            cfrow.MD_PROP_UID = new Guid(PSICustomFields.GetMD_PROP_UID(name));
            cfrow.CODE_VALUE = ltcode;
            cfrow.CUSTOM_FIELD_UID = Guid.NewGuid();
            resDS.ResourceCustomFields.AddResourceCustomFieldsRow(cfrow);
        }

        public static void CreateProjectResource(Guid prjID, string name, Guid resGuid, int resourceType, ProjectWS.ProjectDataSet projectDS)
        {
            ProjectWS.ProjectDataSet.ProjectResourceRow resourceRow = projectDS.ProjectResource.NewProjectResourceRow();

            resourceRow.PROJ_UID = prjID;
            resourceRow.RES_UID = resGuid;
            resourceRow.RES_NAME = name;
            resourceRow.RES_TYPE = resourceType;
            projectDS.ProjectResource.AddProjectResourceRow(resourceRow);
        }

        public static void AddResourceToTeam(Guid prjID, Guid resID, string resname, ProjectWS.ProjectTeamDataSet teamDS)
        {
            ProjectWS.ProjectTeamDataSet.ProjectTeamRow resrow = teamDS.ProjectTeam.NewProjectTeamRow();
            resrow.RES_UID = Guid.NewGuid();
            resrow.NEW_RES_UID = resID;
            resrow.RES_NAME = resname;
            resrow.PROJ_UID = prjID;
            teamDS.ProjectTeam.AddProjectTeamRow(resrow);
        }

        public static Guid GetResourceGuid(string resourceName)
        {
            ResourceWS.ResourceDataSet resourceDs = new ResourceWS.ResourceDataSet();

            PSLibrary.Filter resourceFilter = new Microsoft.Office.Project.Server.Library.Filter();
            resourceFilter.FilterTableName = resourceDs.Resources.TableName;
            resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
            resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
            PSLibrary.Filter.FieldOperator existingResource = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, resourceDs.Resources.RES_NAMEColumn.ColumnName, resourceName);
            resourceFilter.Criteria = existingResource;
            resourceDs = Program.resource.ReadResources(resourceFilter.GetXml(), false);
            if (resourceDs.Resources.Count >= 1)
            {
                return resourceDs.Resources[0].RES_UID;
            }
            else
            {
                return Guid.Empty;
            }
        }

        public static Guid GetResourceUidFromNtAccount(String ntAccount, out bool isWindowsUser)
        {
            ResourceWS.ResourceDataSet rds = new ResourceWS.ResourceDataSet();

            PSLibrary.Filter filter = new PSLibrary.Filter();
            filter.FilterTableName = rds.Resources.TableName;

            PSLibrary.Filter.Field ntAccountField1 = new PSLibrary.Filter.Field(rds.Resources.TableName, rds.Resources.WRES_ACCOUNTColumn.ColumnName);
            filter.Fields.Add(ntAccountField1);

            PSLibrary.Filter.Field ntAccountField2 = new PSLibrary.Filter.Field(rds.Resources.TableName, rds.Resources.RES_IS_WINDOWS_USERColumn.ColumnName);
            filter.Fields.Add(ntAccountField2);

            PSLibrary.Filter.FieldOperator op = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, rds.Resources.WRES_ACCOUNTColumn.ColumnName, ntAccount);
            filter.Criteria = op;

            rds = Program.resource.ReadResources(filter.GetXml(), false);
            isWindowsUser = rds.Resources[0].RES_IS_WINDOWS_USER;
            return (Guid)rds.Resources.Rows[0]["RES_UID"];
        }
    }

    class ResourceDerived : ResourceWS.Resource
    {
        private static String contextString = String.Empty;

        /// <summary>
        /// Override the GetWebRequest method and add the two Web request headers.
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest webRequest = base.GetWebRequest(uri);
            if (contextString != String.Empty)
            {
                webRequest.UseDefaultCredentials = true;

                bool isImpersonating =
                    (System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
                webRequest.Credentials = CredentialCache.DefaultCredentials;

                webRequest.Headers.Add("PjAuth", contextString);
                webRequest.Headers.Add("ForwardedFrom", "/_vti_bin/psi/resource.asmx");

                webRequest.PreAuthenticate = true;
            }
            return webRequest;
        }

        public static void SetImpersonationContext(bool isWindowsUser, String userAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
        {
            contextString = GetImpersonationContext(isWindowsUser, userAccount, userGuid, trackingGuid, siteId, lcid);
        }

        private static String GetImpersonationContext(bool isWindowsUser, String userAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
        {
            PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userAccount, userGuid, trackingGuid, siteId, lcid);
            String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo);
            return contextString;
        }
    }
}
